namespace SimpleWebServices.Web.Mvc
{
    using System;
    using System.Web;
    using System.Web.Mvc;
    using Moq;
    using SimpleWebServices.Web;
    using Xunit;

    public sealed class CacheControlAttributeFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<CacheControlAttribute>()
                .DerivesFrom<ActionFilterAttribute>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .IsDecoratedWith<AttributeUsageAttribute>()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new CacheControlAttribute());
        }

        [Fact]
        public void op_OnActionExecuted_ActionExecutedContextNull()
        {
            Assert.Throws<ArgumentNullException>(() => new CacheControlAttribute().OnActionExecuted(null));
        }

        [Fact]
        public void op_OnActionExecuted_ActionExecutedContextNullModel()
        {
            var mock = new Mock<HttpContextBase>();
            mock.SetupGet<HttpResponseBase>(x => x.Response).Returns(new Mock<HttpResponseBase>().Object).Verifiable();

            new CacheControlAttribute().OnActionExecuted(new ActionExecutedContext()
            {
                HttpContext = mock.Object,
                Controller = new TestController<Resource>()
            });

            mock.VerifyAll();
        }

        [Fact]
        public void op_OnActionExecuted_ActionExecutedContextWithModelETag()
        {
            string etag = "xxxyz";

            var mock = new Mock<HttpContextBase>();
            mock.Setup(x => x.Response.Cache.SetCacheability(HttpCacheability.Public)).Verifiable();
            mock.Setup(x => x.Response.Cache.SetETag(etag)).Verifiable();

            Resource resource = new GenericResource
            {
                Cacheability = HttpCacheability.Public,
                Etag = etag
            };

            new CacheControlAttribute().OnActionExecuted(new ActionExecutedContext
            {
                HttpContext = mock.Object,
                Controller = new TestController<Resource>(resource)
            });

            mock.VerifyAll();
        }

        [Fact]
        public void op_OnActionExecuted_ActionExecutedContextWithModelExpires()
        {
            DateTime expires = DateTime.UtcNow;

            var mock = new Mock<HttpContextBase>();
            mock.Setup(x => x.Response.Cache.SetCacheability(HttpCacheability.Public)).Verifiable();
            mock.Setup(x => x.Response.Cache.SetExpires(expires)).Verifiable();

            Resource resource = new GenericResource
            {
                Cacheability = HttpCacheability.Public,
                Expires = expires
            };

            new CacheControlAttribute().OnActionExecuted(new ActionExecutedContext
            {
                HttpContext = mock.Object,
                Controller = new TestController<Resource>(resource)
            });

            mock.VerifyAll();
        }

        [Fact]
        public void op_OnActionExecuted_ActionExecutedContextWithModelLastModified()
        {
            HttpCacheability cacheability = HttpCacheability.Public;
            DateTime modified = DateTime.UtcNow;

            var mock = new Mock<HttpContextBase>();
            mock.Setup(x => x.Response.Cache.SetCacheability(cacheability)).Verifiable();
            mock.Setup(x => x.Response.Cache.SetLastModified(modified)).Verifiable();

            Resource resource = new GenericResource
            {
                Cacheability = cacheability,
                Modified = modified
            };

            new CacheControlAttribute().OnActionExecuted(new ActionExecutedContext
            {
                HttpContext = mock.Object,
                Controller = new TestController<Resource>(resource)
            });

            mock.VerifyAll();
        }
    }
}